package com.openlogic.system.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.stp.StpUtil;
import com.mybatisflex.core.paginate.Page;
import com.openlogic.common.core.constants.CacheConstant;
import com.openlogic.common.core.enums.BusinessType;
import com.openlogic.common.core.web.controller.BaseController;
import com.openlogic.common.core.web.domain.PageData;
import com.openlogic.common.core.web.domain.entity.UserOnline;
import com.openlogic.common.core.web.domain.model.LoginUser;
import com.openlogic.common.datasource.annotation.QzLog;

import org.noear.solon.annotation.*;
import org.noear.solon.auth.annotation.AuthPermissions;
import org.noear.solon.core.handle.Result;

import java.util.ArrayList;
import java.util.List;

/**
 * 在线用户监控
 * @author xm
 */
@Controller
@Mapping("online")
public class UserOnlineController extends BaseController {

    /**
     * 查询在线用户列表
     */
    @AuthPermissions("monitor:online:list")
    @Get
    @Mapping("list")
    public PageData<UserOnline> list(Page<UserOnline> page, UserOnline userOnline) {
        // 获取所有已登录的会话id（同一账号在多个设备登录只算作一个会话id）
        List<String> sessionIdList = StpUtil.searchSessionId("", 0, -1, false);
        List<UserOnline> userOnlineList = new ArrayList<>();
        for (String sessionId : sessionIdList) {
            // 根据会话id，查询对应的 SaSession 对象，此处一个 SaSession 对象即代表一个登录的账号
            SaSession session = StpUtil.getSessionBySessionId(sessionId);
            UserOnline uo = new UserOnline();
            List<UserOnline.Device> devices = new ArrayList<>();
            // 查询这个账号都在哪些设备登录了（tokenSignList.size()即为登录的设备数）
            List<TokenSign> tokenSignList = session.getTokenSignList();
            for (TokenSign tokenSign : tokenSignList) {
                // 获取指定 Token 的 Token-Session 对象
                SaSession tokenSession = StpUtil.getTokenSessionByToken(tokenSign.getValue());
                LoginUser loginUser = tokenSession.getModel(CacheConstant.LOGIN_USER_KEY, LoginUser.class);
                uo.setUserid(loginUser.getUserid());
                uo.setUserName(loginUser.getUsername());
                uo.setNickName(loginUser.getSysUser().getNickName());
                uo.setDeptName(loginUser.getSysUser().getDept().getDeptName());
                UserOnline.Device device = uo.new Device();
                device.setToken(tokenSession.getToken());
                device.setDeviceType(tokenSign.getDevice());
                device.setLoginIp(loginUser.getIpaddr());
                device.setLoginTime(loginUser.getLoginTime());
                devices.add(device);
            }
            uo.setDevices(devices);
            userOnlineList.add(uo);
        }
        return getPageData(userOnlineList);
    }

    /**
     * 强退所有用户
     */
    @QzLog(title = "在线用户", businessType = BusinessType.FORCE)
    @AuthPermissions("monitor:online:batchLogout")
    @Delete
    @Mapping("forceLogoutAll/{userIds}")
    public Result<Void> forceLogoutAll(@Path Long[] userIds) {
        for (Long userId : userIds) {
            StpUtil.logout(userId);
        }
        return Result.succeed();
    }

    /**
     * 强退用户
     */
    @AuthPermissions("monitor:online:forceLogout")
    @QzLog(title = "在线用户", businessType = BusinessType.FORCE)
    @Delete
    @Mapping("{token}")
    public Result<Void> forceLogout(@Path String token) {
        StpUtil.logoutByTokenValue(token);
        return Result.succeed();
    }

}
